/*
 * 文 件 名:  XmlWriter.java
 * 版    权:  Ysten Technologies Co., Ltd. Copyright YYYY-YYYY,  All rights reserved
 * 描    述:  <使用betixt将对象转换成xml字符串的工具类>
 * 修 改 人:  bingbing
 * 修改时间:  2014年5月28日
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.example.demobetwixt;


import com.example.demobetwixt.po.Clss;
import com.example.demobetwixt.po.Score;
import com.example.demobetwixt.po.Student;
import org.apache.commons.betwixt.io.BeanWriter;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.ResourceUtils;
import org.xml.sax.InputSource;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

/**
 * <使用betixt将对象转换成xml字符串的工具类>
 */
public class XmlWriter {
    private static Logger logger = LoggerFactory.getLogger(XmlWriter.class);

    public static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";


    /**
     * xml的换行符
     */
    private static final String XML_ENDLINE = "\r\n";

    /**
     * betwixt文件路径
     */
    public static final String BETWIXTFILE_PATH = "betwixt/";

    /**
     * betwixt文件格式
     */
    private static final String BETWIXTFILT_FORMAT = ".betwixt";

    private static final String PRTTY_SPAN = "  ";


    /**
     * @param clazz          class
     * @param obj            对象
     * @param filePath       betwixt模板的路径（xml约束模板）
     * @param endTag         结束标记
     * @param writeEmptyNode 是否写空节点
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> String objToXml(Class<T> clazz, Object obj, String filePath, boolean endTag, boolean writeEmptyNode)
            throws IOException {
        String fileName = filePath + clazz.getSimpleName() + BETWIXTFILT_FORMAT;

        InputStream in = null;
        try {
            in = loadFile(fileName, false);
            return writeXml(in, obj, endTag, writeEmptyNode);
        } finally {
            IOUtilsExpand.closeQuietly(in);
        }




    }


    /**
     * @param clazz      class
     * @param obj        对象
     * @param writeEmpty 是否写空节点
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> String objToXml(Class<T> clazz, Object obj, boolean writeEmpty)
            throws Exception {
        String loadFileName = BETWIXTFILE_PATH + clazz.getSimpleName() + BETWIXTFILT_FORMAT;
        InputStream in = null;
        try {
            in = loadFile(loadFileName, false);
            return writeXml(in, obj, true, writeEmpty);
        } finally {
            IOUtilsExpand.closeQuietly(in);
        }


    }


    public static void main(String[] args) throws Exception {


        //使用betwxit把java对象转为多层嵌套xml

        Clss c1 = new Clss();
        c1.setId(1);
        c1.setName("qewrr");

        Student s1 = new Student();
        s1.setName("aaa");
        s1.setScore(new Score(123));

        Student s2 = new Student();
        s2.setName("bbb");
        s2.setScore(new Score(213));
        List<Student> students = new ArrayList<>();
        students.add(s1);
        students.add(s2);
        c1.setStudents(students);


        String resultStr =  objToXml(Clss.class , c1 , true);
        System.out.println(resultStr);


        //<?xml version="1.0" encoding="UTF-8"?>
        //  <clss id="1" name="qewrr">
        //    <students>
        //      <student>
        //        <name>aaa</name>
        //        <score>
        //          <mathScore>123</mathScore>
        //        </score>
        //      </student>
        //      <student>
        //        <name>bbb</name>
        //        <score>
        //          <mathScore>213</mathScore>
        //        </score>
        //      </student>
        //    </students>
        //  </clss>

        //-----------

        //将xml字符串保存为本地xml文件
//        File file=new File("D:\\resultStr.xml");
//        FileOutputStream fos=new FileOutputStream(file);
//        IOUtils.write(resultStr , fos , "utf-8");


//-------------------------------------------------------------------

//        TestObj t22 = new TestObj("qr", 1234);
//
//
//        //独立java对象(没有引用其他java对象)转xml
//        String xmlstr = objToXml(TestObj.class, t22, true);
//        System.out.println(xmlstr);

        //<?xml version="1.0" encoding="UTF-8"?>
        //  <TestObj>
        //    <name>qr</name>
        //    <age>1234</age>
        //  </TestObj>


    }


    /**
     * <将对象obj转成和输入流in格式相同的xml文件>
     *
     * @param in  输入流
     * @param obj 转换的对象
     * @return xml格式的字符串
     * @see [类、类#方法、类#成员]
     */
    private static String writeXml(InputStream in, Object obj, boolean endTag, boolean writeEmptyNode) {
        StringBuilder result = new StringBuilder();
        StringWriter stringWriter = new StringWriter();

        BeanWriter beanWriter = new BeanWriter(stringWriter);


        try {
            InputSource source = new InputSource(in);

            beanWriter.getXMLIntrospector().register(source);
            beanWriter.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(false);
            beanWriter.getBindingConfiguration().setMapIDs(false);
            beanWriter.writeXmlDeclaration("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");

            beanWriter.setEndOfLine(XML_ENDLINE);
            beanWriter.setIndent(PRTTY_SPAN);
            beanWriter.setEndTagForEmptyElement(endTag);
            beanWriter.setWriteEmptyElements(writeEmptyNode);
            beanWriter.write(obj);
            result.append(stringWriter.toString());
        } catch (Exception e) {
            logger.error("create xml string error use betwixt, error", e);
        } finally {

            IOUtilsExpand.closeQuietly(stringWriter);
            IOUtilsExpand.closeQuietly(beanWriter);
        }
        return result.toString();

    }

    // comes spring-core:PropertiesLoaderUtils.loadAllProperties
    private static InputStream loadFile(String fileName, boolean isWindows)
            throws IOException {
        if (isWindows) {
            return new FileInputStream(new File(fileName));
        }
        //spring获取类加载器
        ClassLoader loader = ClassUtils.getDefaultClassLoader();
        URL url = loader.getResource(fileName);
        URLConnection con = url.openConnection();
        //必要时使用缓存
        ResourceUtils.useCachesIfNecessary(con);
        return con.getInputStream();
    }


}
